package com.yoyo.itravel.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Utils {

    private static final String ENCRYPTION_TYPE = "MD5"; // 加密方法（MD5加密）

    // 私有化构造器
    private MD5Utils() {

    }

    public static String md5(String initStr) {
        // 声明一个byte数组，用于存储密文字节数组
        byte[] secretBytes = null;

        if (StringUtils.isEmpty(initStr)) {
            return null;
        }

        try {
            // 将明文转为字节数组
            byte[] bytes = initStr.getBytes();
            // 构建MD5加密工具对象
            MessageDigest messageDigest = MessageDigest.getInstance(ENCRYPTION_TYPE);
            // MD5加密算法是需要信息的长度减去448能被512整除，所以第二步是对信息的填充和打乱
            messageDigest.update(bytes);
            // 对摘要后的信息进行哈希计算得到一个16字节的字节数组
            secretBytes = messageDigest.digest();
//            for (byte secretByte : secretBytes) {
//                System.out.println(secretByte);
//            }
            // 返回
            return byteArrayToHex(secretBytes);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException("没有md5这个算法！");
        }

          // signum - 该数的正负号（-1 表示负，0 表示零，1 表示正）。
//        // 将这个字节数组转成16进制数
//        String md5Code = new BigInteger(1, secretBytes).toString(16);
//        // 将md5字符串变成32位【不足前面补0】
//        for (int i = 0; i < 32 - md5Code.length(); i++) {
//            md5Code = "0" + md5Code;
//        }
    }

    /**
     * @Description 将字节数组换成成16进制的字符串
     *
     * @param secretBytes
     * @return java.lang.String
     */
    private static String byteArrayToHex(byte[] secretBytes) {

        // 用来将字节转换成 16 进制表示的字符
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

        char[] resultCharArray = new char[16 * 2]; // 每个字节用 16 进制表示的话，使用两个字符
        int k = 0; // 表示转换结果中对应的字符位置

        // 从第一个字节开始，对每一个字节,转换成 16 进制字符的转换
        for (int i = 0; i < 16; i++) {
            // 取第 i 个字节
            byte byte0 = secretBytes[i];
            // 取字节中高 4 位的数字转换, >>> 为逻辑右移，将符号位一起右移
            resultCharArray[k++] = hexDigits[byte0 >>> 4 & 0xf];
            // 取字节中低 4 位的数字转换
            resultCharArray[k++] = hexDigits[byte0 & 0xf];
        }

        // 换后的结果转换为字符串，返回
        return new String(resultCharArray );
    }

}
